"""矩阵分解模块
包含LU分解、QR分解、Cholesky分解、SVD等功能
"""
import numpy as np
from scipy.linalg import lu, qr, cholesky, svd, schur
from typing import Tuple, Optional, Union
import warnings

class MatrixDecomposition:
    @staticmethod
    def lu_decomposition(matrix: np.ndarray, permute_l: bool = False) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
        """
        LU分解（带部分选主元）
        :param matrix: 输入矩阵
        :param permute_l: 是否返回置换的L矩阵
        :return: (P, L, U) 或 (L, U, P)
        """
        P, L, U = lu(matrix, permute_l=permute_l)
        return P, L, U
    
    @staticmethod
    def qr_decomposition(matrix: np.ndarray, mode: str = 'economic') -> Tuple[np.ndarray, np.ndarray]:
        """
        QR分解
        :param matrix: 输入矩阵
        :param mode: 分解模式 ('full', 'economic')
        :return: (Q, R)
        """
        Q, R = qr(matrix, mode=mode)
        return Q, R
    
    @staticmethod
    def cholesky_decomposition(matrix: np.ndarray, lower: bool = True) -> np.ndarray:
        """
        Cholesky分解（对称正定矩阵）
        :param matrix: 输入对称正定矩阵
        :param lower: 是否返回下三角矩阵
        :return: L (如果lower=True) 或 U (如果lower=False)
        """
        try:
            return cholesky(matrix, lower=lower)
        except np.linalg.LinAlgError:
            raise ValueError("Matrix is not positive definite")
    
    @staticmethod
    def svd_decomposition(matrix: np.ndarray, full_matrices: bool = True) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
        """
        奇异值分解
        :param matrix: 输入矩阵
        :param full_matrices: 是否计算完整的U和V矩阵
        :return: (U, s, Vh)
        """
        U, s, Vh = svd(matrix, full_matrices=full_matrices)
        return U, s, Vh
    
    @staticmethod
    def schur_decomposition(matrix: np.ndarray, output: str = 'real') -> Tuple[np.ndarray, np.ndarray]:
        """
        Schur分解
        :param matrix: 输入方阵
        :param output: 输出类型 ('real', 'complex')
        :return: (T, Z) 其中 A = Z @ T @ Z.H
        """
        T, Z = schur(matrix, output=output)
        return T, Z
    
    @staticmethod
    def jordan_normal_form(matrix: np.ndarray, tol: float = 1e-10) -> Tuple[np.ndarray, np.ndarray]:
        """
        Jordan标准形计算（数值近似）
        :param matrix: 输入方阵
        :param tol: 容差
        :return: (J, P) 其中 A = P @ J @ P^(-1)
        """
        eigenvals, eigenvecs = np.linalg.eig(matrix)
        
        # 简化版Jordan形式（假设可对角化）
        J = np.diag(eigenvals)
        P = eigenvecs
        
        return J, P